import React, { Fragment } from 'react';
import { FormattedMessage, intlShape } from 'react-intl';
import PropTypes from 'prop-types';
import TetherComponent from 'react-tether';
import RootCloseWrapper from 'react-overlays/lib/RootCloseWrapper';
import moment from 'moment-timezone';
import contains from 'dom-helpers/query/contains';
import debounce from 'lodash/debounce';
import uniqueId from 'lodash/uniqueId';
import noop from 'lodash/noop';

import {
  IconButton,
  Row,
  Col,
  TextField,
  Button
} from '@folio/stripes/components';
import Calendar from './CalendarDoublePerfect';
import css from './CalendarPerfect.css';
import TimePerfectChoice from './TimePerfectChoice';
import SuperTimeChoice from './SuperTimeChoice';
import SuperDropDown from './SuperDropDown';

const defaultParser = (value, timeZone, dateFormat) => {
  if (!value || value === '') {
    return value;
  }

  const offsetRegex = /T[\d.:]+[+-][\d]+$/;
  let inputMoment;
  // if date string contains a utc offset, we can parse it as utc time and convert it to selected timezone.
  if (offsetRegex.test(value)) {
    inputMoment = moment.tz(value, timeZone);
  } else {
    inputMoment = moment.tz(value, dateFormat, timeZone);
  }
  const inputValue = inputMoment.format(dateFormat);
  return inputValue;
};

const propTypes = {
  autoFocus: PropTypes.bool,
  backendDateStandard: PropTypes.string,
  date: PropTypes.object,
  dateFormat: PropTypes.string,
  disabled: PropTypes.bool,
  exclude: PropTypes.func,
  hideOnChoose: PropTypes.bool,
  id: PropTypes.string,
  input: PropTypes.object,
  inputRef: PropTypes.object,
  label: PropTypes.node,
  locale: PropTypes.string,
  meta: PropTypes.object,
  onChange: PropTypes.func,
  onSetDate: PropTypes.func,
  parser: PropTypes.func,
  readOnly: PropTypes.bool,
  required: PropTypes.bool,
  screenReaderMessage: PropTypes.string,
  showCalendar: PropTypes.bool,
  tether: PropTypes.object,
  timeZone: PropTypes.string,
  useFocus: PropTypes.bool,
  value: PropTypes.string,
};

const contextTypes = {
  intl: intlShape
};

const defaultProps = {
  autoFocus: false,
  backendDateStandard: 'ISO8601',
  hideOnChoose: true,
  parser: defaultParser,
  screenReaderMessage: '',
  tether: {
    attachment: 'top center',
    targetAttachment: 'bottom center',
    optimizations: {
      gpu: false,
    },
    constraints: [{
      to: 'window',
      attachment: 'together',
    },
    {
      to: 'scrollParent',
      pin: true,
    },
    ],
  },
  useFocus: true,
};

class DateSuperCalendarChoice extends React.Component {
    static propTypes = propTypes;
    static contextTypes = contextTypes;
    static defaultProps = defaultProps;

    constructor(props, context) {
      super(props);

      this.startPicker = null;
      this.endPicker = null;
      this.container = null;
      this.srSpace = null;
      this.textfield = props.inputRef || React.createRef();
      this.hiddenInput = React.createRef();
      this.startTimePicker = React.createRef();
      this.endTimePicker = React.createRef();
      this.dbhideCalendar = debounce(this.hideCalendar, 10);

      const timeZone = props.timeZone || context.intl.timeZone;
      const locale = props.locale || context.intl.locale;
      moment.locale(locale);

      const dateFormat = 'YYYY-MM-DD';

      this.state = {
        dateString: '',
        showCalendar: this.props.showCalendar || false,
        srMessage: '',
        dateFormat,
        timeZone,
        prevValue: '',
        locale,
        timeNumber: [],
        dateNumber: [],
        startLightTime: 'HH',
        startRightTime: 'mm',
        endLightTime: 'HH',
        endRightTime: 'mm',
        dateStartString: 'YYYY-MM-DD',
        dateEndString: 'YYYY-MM-DD',
        startTime: new Date(),
             endTime: new Date()

      };

      if (props.id) {
        this.testId = props.id;
      } else {
        this.testId = uniqueId('dp-');
      }
    }

    /* gDSFP handles instances where the value is transitioning from an empty string
    * to some value.
    */
    static getDerivedStateFromProps(props, state) {
      if (!state.prevValue) {
        const timeZone = props.timeZone || state.timeZone;
        const dateFormat = props.dateFormat || state.dateFormat;

        let inputValue = '';
        if (!props.input && !props.date) {
          inputValue = props.parser(props.value, timeZone, dateFormat, state.locale);
        } else {
          inputValue = props.parser(props.input.value, timeZone, dateFormat, state.locale);
        }
        return {
          dateString: inputValue,
          prevValue: props.input ? props.input.value : props.value,
          hiddenValue: props.input ? props.input.value : '',
        };
      }

      return null;
    }

    componentDidUpdate() {
      const {
        input,
        onChange
      } = this.props;

      const {
        changeType,
      } = this.state;

      if (changeType && changeType !== 'invalid') {
        const baseEvent = {
          stopPropagation: noop,
          preventDefault: noop
        };

        if (input && this.hiddenInput.current) {
          input.onChange(
            { ...baseEvent, target: this.hiddenInput.current}
          );
        } else if (onChange && this.textfield.current) {
          onChange(
            { ...baseEvent, target: this.textfield.current}
          );
        }
        this.internalSetState({ changeType: undefined });
      }
    }

    textfield = React.createRef();

    handleFieldFocus = () => {
      if (this.props.useFocus && !this.props.disabled) {
        this.showCalendar();
      }
    }

    handleFieldClick = () => {
      if (this.props.useFocus) {
        if (!this.state.showCalendar) {
          this.showCalendar();
        }
      }
    }

    handleRootClose = (e) => {
      // used by <RootCloseWrapper> to determine whether or not it should hide the picker.
      // it should determine that the element that's focused is outside of the DatePerfectChoice's containing div and
      // the calendar widget (this.picker).
      if (!contains(this.container, e.target)) {
        if (!this.DatePerfectChoiceIsFocused()) {
          this.hideCalendar();
        }
      }
    }

    showCalendar = () => {
      const { input } = this.props;
      if (!!input.value && input.value.search(' / ') != -1) {
        const value = input.value.split(' / ');

        const timeValue1 = value[0];
        const timeValue2 = value[0];

        const dateStartString = moment(new Date(timeValue1)).format('YYYY-MM-DD');
        const time = moment(new Date(timeValue2)).format('HH:mm:ss');
        const startTime = time;

        const timeValue3 = value[1];
        const timeValue4 = value[1];

        const dateEndString = moment(new Date(timeValue3)).format('YYYY-MM-DD');
        const timeEnd = moment(new Date(timeValue4)).format('HH:mm:ss');
        const endTime = timeEnd;

        this.setState({
          dateEndString,
          dateStartString,
          startTime,
          endTime,
          showCalendar: true,
        });
        return false;
      } else {
        const date = new Date();
        const startTime = moment(date).format('HH:mm:ss');
        const endTime = startTime;
        this.setState({
          startTime,
          endTime,

          showCalendar: true,
        });
      }
    }

    hideCalendar = () => {
      this.setState({
        showCalendar: false,
      });
    }

    toggleCalendar = () => {
      const current = this.state.showCalendar;
      this.setState({
        showCalendar: !current,
      });
    }

    handleKeyDown = (e) => {
      if (this.startPicker) {
        const curDate = this.startPicker.getCursorDate();
        const formattedDate = curDate.format(this.state.dateFormat);
        let dateString;

        switch (e.keyCode) {
          case 40: // down
            e.preventDefault();
            dateString = this.startPicker.nextWeek();
            break;
          case 38: // up
            e.preventDefault();
            dateString = this.startPicker.previousWeek();
            break;
          case 37: // left
            dateString = this.startPicker.previousDay();
            break;
          case 39: // right
            dateString = this.startPicker.nextDay();
            break;
          case 27: // escape
            e.preventDefault();
            this.hideCalendar();
            break;
          case 34: // pgDn
            e.preventDefault();
            if (!this.state.showCalendar) {
              return;
            }
            if (!e.altKey) {
              dateString = this.startPicker.nextMonth();
            } else {
              dateString = this.startPicker.nextYear();
            }
            break;
          case 33: // pgUp
            e.preventDefault();
            if (!this.state.showCalendar) {
              return;
            }
            if (!e.altKey) {
              dateString = this.startPicker.previousMonth();
            } else {
              dateString = this.startPicker.previousYear();
            }
            break;
          case 13: // enter
            e.preventDefault();
            if (this.state.showCalendar) {
              this.handleSetDate(e, curDate, formattedDate);
            } else {
              this.showCalendar();
            }
            dateString = (
                      <FormattedMessage
                          id="ui-party.stripes-components.dateSelected"
                          values={{ date: formattedDate }}
                        />
            );
            break;
          case 9: // tab
            this.hideCalendar();
            break;
          default:
        }
        this.informScreenReader(`${dateString}`);
      } else {
        switch (e.keyCode) {
          case 13: // enter
          case 40: // down
            e.preventDefault();
            this.showCalendar();
            break;
          default:
        }
      }
    }

    internalSetState = (state, changeType, callbacks) => {
      this.setState(curState => {
        return { ...curState, ...state, changeType};
      },
      () => {
        if (callbacks) {
          callbacks.forEach((cb) => {
            cb(this.state);
          });
        }
      });
    }

    handleSetStartDate = (e, date, stringDate) => {
      const isValidDate = moment(stringDate, this.state.dateFormat, true).isValid();

      let standardizedDate;

      if (e.type === 'click' || e.type === 'keydown') {
        e.preventDefault();
        this.textfield.current.focus();

        if (isValidDate) {
          standardizedDate = this.standardizeDate(stringDate);
          const dateEndString = dateEndStringInit(stringDate);
          this.internalSetState(
            {
              dateStartString: stringDate,
              hiddenValue: standardizedDate,
              prevValue: stringDate,
              dateEndString
            },
            'calendar',
          );
        }
      } else if (e.type === 'change') {
        const tempString = e.target.value;
        const dateEndString = dateEndStringInit(e.target.value);
        if (moment(tempString, this.state.dateFormat, true).isValid()) {
          standardizedDate = this.standardizeDate(e.target.value);
          this.internalSetState(
            {
              dateStartString: e.target.value,
              hiddenValue: standardizedDate,
              prevValue: e.target.value,
              dateEndString
            },
            'validEntry',
          );
        } else {
          const dateEndString = dateEndStringInit(e.target.value);
          this.internalSetState(
            {
              dateStartString: e.target.value,
              hiddenValue: '',
              dateEndString
            },
            'invalid'
          );
        }
      }
      function dateEndStringInit(stringDate) {
        return moment(new Date(stringDate)).add(1, 'days').format('YYYY-MM-DD');
      }
    }

    handleSetEndDate = (e, date, stringDate) => {
      const isValidDate = moment(stringDate, this.state.dateFormat, true).isValid();

      let standardizedDate;

      if (e.type === 'click' || e.type === 'keydown') {
        e.preventDefault();
        this.textfield.current.focus();

        if (isValidDate) {
          standardizedDate = this.standardizeDate(stringDate);

          this.internalSetState(
            {
              dateEndString: stringDate,
              hiddenValue: standardizedDate,
              prevValue: stringDate,
            },
            'calendar',
          );
        }
      } else if (e.type === 'change') {
        const tempString = e.target.value;

        if (moment(tempString, this.state.dateFormat, true).isValid()) {
          standardizedDate = this.standardizeDate(e.target.value);
          this.internalSetState(
            {
              dateEndString: e.target.value,
              hiddenValue: standardizedDate,
              prevValue: e.target.value,
            },
            'validEntry',
          );
        } else {
          this.internalSetState(
            {
              dateEndString: e.target.value,
              hiddenValue: '',
            },
            'invalid'
          );
        }
      }
    }

    handleFieldChange = (e) => {
      if (e.target.value === '') {
        this.clearDate();
      } else {
        this.handleSetDate(e, e.target.value, e.target.value);
      }
    }

    clearDate = () => {
      this.internalSetState(
        {
          dateString: '',
          hiddenValue: '',
        },
        'clear',
      );
    }

    cleanForScreenReader(str) {
      return str.replace(/Y/g, 'Y ');
    }

    informScreenReader(str) {
      this.setState({ srMessage: str });
    }

    DatePerfectChoiceIsFocused() {
      if (contains(this.container, document.activeElement) &&
            document.activeElement !== document.body) {
        if (this.startPicker) {
          return (contains(this.startPicker.getDOMContainer(), document.activeElement));
        }
        return true;
      }
      return false;
    }

    hideOnBlur = (e) => {
      const {
        input
      } = this.props;

      if (this.DatePerfectChoiceIsFocused()) {
        if (input && input.onBlur) {
          input.onBlur(e);
        }
        this.hideCalendar();
        this.setState({ srMessage: '' });
      }
    }

    standardizeDate(date) {
      const parsed = moment.tz(date, this.state.dateFormat, this.state.timeZone).isValid;

      if (parsed) {
        return date;
      }
      date = moment(new Date()).format('YYYY-MM-DD');
      return date;
    }

    renderCalendar() {
      const { startExclude, input } = this.props;

      return (

          <Calendar
              onSetDate={this.handleSetStartDate}
              selectedDate={this.state.dateStartString}
              dateFormat={this.state.dateFormat}
              ref={(ref) => {
                  this.startPicker = ref;
                }}
              onKeyDown={this.handleKeyDown}
              onBlur={this.hideCalendar}
              locale={this.state.locale}
              exclude={startExclude}
              id={this.testId}

            />

      );
    }

    renderEndCalendar() {
      const { endExclude, input } = this.props;

      return (
          <Calendar
              onSetDate={this.handleSetEndDate}
              selectedDate={this.state.dateEndString}
              dateFormat={this.state.dateFormat}
              ref={(ref) => {
                  this.endPicker = ref;
                }}
              onKeyDown={this.handleKeyDown}
              onBlur={this.hideCalendar}
              locale={this.state.locale}
              exclude={endExclude}
              id={this.testId}
            />

      );
    }

    renderEndElement() {
      return (
          <>
                {this.state.dateString !== '' && (
                    <FormattedMessage id="ui-party.stripes-components.clearFieldValue">
                        {ariaLabel => (
                            <IconButton
                                data-test-clear
                                key="clearButton"
                                onClick={this.clearDate}
                                aria-label={ariaLabel}
                                id={`DatePerfectChoice-clear-button-${this.testId}`}
                                tabIndex="-1"
                                icon="times-circle-solid"
                            />
                        )}
                    </FormattedMessage>
                )}
                <FormattedMessage id="ui-party.stripes-components.showOrHideDatePerfectChoice">
                    {ariaLabel => (
                        <IconButton
                            data-test-calendar-button
                            onClick={this.toggleCalendar}
                            onKeyDown={this.handleKeyDown}
                            aria-label={ariaLabel}
                            id={`DatePerfectChoice-toggle-calendar-button-${this.testId}`}
                            tabIndex="-1"
                            icon="calendar"
                        />
                    )}
                </FormattedMessage>
            </>
      );
    }

    renderInput() {
      const {
        input,
        screenReaderMessage,
        label,
        readOnly,
        required,
        disabled,
        autoFocus,
        placeholder
      } = this.props;

      const {
        dateFormat,
      } = this.state;

      const screenReaderFormat = this.cleanForScreenReader(this.state.dateFormat);

      let ariaLabel;
      if (readOnly || disabled) {
        ariaLabel = `${label}`;
      } else {
        ariaLabel = (
              <FormattedMessage
                  id="ui-party.stripes-components.screenReaderLabel"
                  values={{ label, screenReaderFormat, screenReaderMessage }}
                />
        );
      }

      let textfieldProps = {
        label,
        readOnly,
        disabled,
        required,
        autoFocus,
        'id': this.testId,
        'inputRef': this.textfield,
        'onChange': this.handleSetDate,
        'value': this.state.dateString,
        'aria-label': ariaLabel,
        'placeholder': placeholder || `${dateFormat}`,
        'onBlur': this.hideOnBlur,
        'hasClearIcon': false,
        'autoComplete': 'off',
      };

      if (!readOnly && !disabled) {
        textfieldProps = {
          ...textfieldProps,
          endControl: this.renderEndElement(),
          onKeyDown: this.handleKeyDown,
          onClick: this.handleFieldClick,
          onFocus: this.handleFieldFocus
        };
      }

      if (this.props.input && this.props.meta) {
        textfieldProps = {
          ...textfieldProps,
          meta: this.props.meta,
          input: { ...input, value: this.state.dateString },
          onChange: this.handleFieldChange,
          onBlur: (e) => {
            input.onBlur();
            e.preventDefault();
          }
        };
      }

      return <TextField {...textfieldProps} />;
    }

    saveInput = () => {
      const startTime = this.startTimePicker.current.getTimeString();
      const endTime = this.endTimePicker.current.getTimeString();
      const check = /([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/;
      const checkYear = /(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))| ((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29)$/;
      if (!check.test(startTime)) {
        alert('请选择一个正确开始时间');
        return false;
      }
      if (!check.test(endTime)) {
        alert('请选择一个正确结束时间');
        return false;
      }
      if (!checkYear.test(this.state.dateStartString)) {
        alert('请选择一个正确开始日期');
        return false;
      }
      if (!checkYear.test(this.state.dateEndString)) {
        alert('请选择一个正确结束日期');
        return false;
      }
      let str = `${this.state.dateStartString} ${startTime} / ${this.state.dateEndString} ${endTime}`;
      const data1 = new Date(this.state.dateStartString);
      const data2 = new Date(this.state.dateEndString);
      if (data1.getTime() === data2.getTime()) {
        const start = new Date(`${this.state.dateStartString} ${startTime} `).getTime();
        const end = new Date(`${this.state.dateStartString} ${endTime} `).getTime();
        if (start === end) {
          alert('开始时间不能与结束时间相同');
        } else if (end < start) {
          str = `${this.state.dateStartString} ${endTime} / ${this.state.dateEndString} ${startTime}`;
        }
      }

      const result = /[a-zA-Z]+/.test(str);

      if (!result) {
        this.props.input.onBlur(str);
        this.setState({
          dateString: str,
          prevValue: str,
          hiddenValue: str,
          startLightTime: 'HH',
          startRightTime: 'mm',
          endLightTime: 'HH',
          endRightTime: 'mm',
          dateStartString: 'YYYY-MM-DD',
          dateEndString: 'YYYY-MM-DD',
        }, () => {
          this.hideCalendar();
        });
      } else {
        alert('时间格式不正确,请重新修改');
      }
    }

    initStartTestTimeChoice = () => {
      return (
          <SuperTimeChoice
              ref={this.startTimePicker}
              type="start"
              timeZone={this.props.timeZone}
              value={this.state.startTime}
              required
            />
      );
    }

    initEndTestTimeChoice = () => {
      return (
         <SuperTimeChoice
              ref={this.endTimePicker}
              type="end"
              timeZone={this.props.timeZone}
              value={this.state.endTime}
              required
            />
      );
    }

    render() {
      const propStyle = {
        'height': '445px',
        'width': '746px',
        'boxShadow': '0 4px 32px rgba(0, 0, 0, 0.175)',
        'borderRadius': '8px',
        'backgroundColor': 'white',
        'border': '1px solid #bcbcbc',
        'transform': 'scale(1)'
      };
      const divStyle = { 'height': '95%', 'border': '1px solid rgb(188, 188, 188)' };
      const heightStyle = { height: '100%' };
      const buttonDivStyle = { 'width': '60%', 'height': '40px', 'margin': '0 auto' };
      const titleStyle = { 'padding':'7px', 'fontWeight':'900' };
      return (
          <TetherComponent {...defaultProps.tether} {...this.props.tether}>
              <div
style={{position: 'relative', width: '100%'}}
ref={(ref) => {
                    this.container = ref;
                }}>
                  <div
                      aria-live="assertive"
                      aria-relevant="additions"
                      className={css.srOnly}
                      ref={(ref) => {
                          this.srSpace = ref;
                        }}
                    >
                      <div>{this.state.srMessage}</div>
                    </div>
                  {this.renderInput()}
                  <input type="hidden" hidden value={this.state.hiddenValue} ref={this.hiddenInput} />
                </div>
              {
                    this.state.showCalendar && <RootCloseWrapper >

                      <form name="register1" id="register1">
                          <div style={propStyle}>

                              <div style={{ height: '32px' }}>
                                  <Row center="xs">
                                      <Col xs={5} style={titleStyle}><span>开始时间</span></Col>
                                      <Col xs={5} style={titleStyle}><span>结束时间</span></Col>
                                    </Row>

                                </div>
                              <Row center="xs" style={{ height: '340px' }}>

                                  <Col xs={5} style={heightStyle}>
                                      <div id="startShowDateTime">
                                          <Row center="xs">
                                              <Col xs={7}>
                                                  <TextField
name="startShowDateTime"
                                                      value={this.state.dateStartString}
disabled 
                                                    />
                                                </Col>
                                              <Col xs={5}>
                                                  {this.initStartTestTimeChoice()}
                                                </Col>
                                            </Row>

                                        </div>
                                      <div style={divStyle}>
                                          {this.renderCalendar()}
                                        </div>
                                    </Col>

                                  <Col xs={5} style={heightStyle}>
                                      <div id="endShowDateTime">
                                          <Row center="xs">
                                              <Col xs={7}>
                                                  <TextField
name={'endShowDateTime'}
value={this.state.dateEndString}
                                                      disabled 
                                                    />
                                                </Col>
                                              <Col xs={5}>
                                                  {this.initEndTestTimeChoice()}
                                                </Col>
                                            </Row>

                                        </div>
                                      <div style={divStyle}>
                                          {this.renderEndCalendar()}
                                        </div>
                                    </Col>

                                </Row>
                              <div style={buttonDivStyle}>
                                  <Button
fullWidth
type="submit"
style={{marginTop: '30px'}}
onClick={() => {
                                        this.saveInput()
                                    }}
                                    >
{' '}
确 定

                                    </Button>
                                </div>
                            </div>
                        </form>
                                              </RootCloseWrapper>

                }

            </TetherComponent>
      );
    }
}

export default DateSuperCalendarChoice;
